package com.gjt.serverSocket;

import java.io.*;
import java.net.URLConnection;
import java.nio.file.Files;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.net.Socket;

/**
 * @author Guojt
 * @date 2024/9/11 8:22
 */
public class RequestProcessor implements Runnable {
    private static final Logger logger = Logger.getLogger(RequestProcessor.class.getCanonicalName());

    private File rootDirectory;
    private Socket connection;
    private String indexFileName = "index.html";

    public RequestProcessor(File rootDirectory, String indexFileName, Socket connection) {
        if (rootDirectory.isFile()) {
            throw new IllegalArgumentException("rootDirectory must be a directory, not a file");
        }
        try {
            // 获取规范化文件路径
            rootDirectory = rootDirectory.getCanonicalFile();
        } catch (IOException e) {

        }
        this.rootDirectory = rootDirectory;

        if (indexFileName != null) this.indexFileName = indexFileName;
        this.connection = connection;
    }

    @Override
    public void run() {
        // 安全检查
        String root = rootDirectory.getParent();

        try (OutputStream raw = new BufferedOutputStream(connection.getOutputStream())) {
            Writer out = new OutputStreamWriter(raw);
            Reader in = new InputStreamReader(new BufferedInputStream(connection.getInputStream()));

            StringBuffer requestLine = new StringBuffer();
            while (true) {
                int c = in.read();
                if (c == '\r' || c == '\n' || c == -1) break;
                requestLine.append((char) c);
            }

            String get = requestLine.toString();
            logger.info(connection.getRemoteSocketAddress() + " " + get);

            String[] tokens = get.split("\\s+");
            String method = tokens[0];
            String version = "";

            if(method.equals("GET")){
                String fileName = tokens[1];
                if(fileName.endsWith("/")) fileName += indexFileName;

                String contextType = URLConnection.getFileNameMap().getContentTypeFor(fileName);

                if(tokens.length > 2){
                    version = tokens[2];
                }

                File theFile = new File(rootDirectory, fileName.substring(1, fileName.length()));
                // 不要让客户超出文档得跟范围之外
                if(theFile.canRead() && theFile.getCanonicalPath().startsWith(root)){
                    byte[] theData = Files.readAllBytes(theFile.toPath());
//                    if(version.startsWith("HTTP/")){// 发送一个mime  首部
//                        sendHeader(out, "HTTP/1.0 200 OK", contextType, theData.length);
//                    }

                    // 发送文件，这个可能是一个图片或者其他二进制文件，所以使用底层输出流，而不是Writer
                    raw.write(theData);
                    raw.flush();
                }else {
                    // 无法找到文件
                    String body = new StringBuilder("<HTML> \r\n")
                            .append("<HEAD><TITLE>File Not Found</TITLE>\r\n")
                            .append("</HEAD>\r\n")
                            .append("</BODY>")
                            .append("<H1>HTTP Error 404: File Not Found</H1>\r\n")
                            .append("</BODY></HTML>\r\n")
                            .toString();
                    if(version.startsWith("HTTP/")){// 发送一个MIME 首部
                        sendHeader(out, "HTTP/1.0 404 File Not Found", "text/html; charset=utf-8", body.length());
                    }

                    out.write(body);

                    out.flush();
                }
            }else {// 方法不是get
                String body = new StringBuilder("<HTML> \r\n")
                        .append("<HEAD><TITLE>Not Implemented</TITLE>\r\n")
                        .append("</HEAD>\r\n")
                        .append("</BODY>")
                        .append("<H1>HTTP Error 501:Not Implemented</H1>\r\n")
                        .append("</BODY></HTML>\r\n")
                        .toString();
                if(version.startsWith("HTTP/")){// 发送一个MIME 首部
                    sendHeader(out, "HTTP/1.0 501 501 Not Implemented", "text/html; charset=utf-8", body.length());
                }
                out.write(body);
                out.flush();
            }
        } catch (IOException e) {
            logger.log(Level.WARNING, "Error talking to " + connection.getRemoteSocketAddress(), e);
        }finally {
            try{
                connection.close();
            }catch (IOException ex){

            }
        }
    }

    private void sendHeader(Writer out, String responseCode, String contentType, int length) throws IOException {
        out.write(responseCode + "\r\n");
        Date now = new Date();
        // 定义日期格式
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

        // 格式化日期
        String formattedDate = dateFormat.format(now);

        out.write("Date: " + formattedDate + "\r\n");
        out.write("Server: JHTTP 2.0\r\n");
        out.write("Content-length: " + length + "\r\n");
        out.write("Content-type: " + contentType + "\r\n");
        out.flush();
    }
}
